﻿using System;
using System.Reflection;

namespace DNX.IoCnoC
{
    public interface IDefaultConstructor
    {
        void Set(ConstructorInfo[] constructorInfoList, TypeHandle configuration);
    }

    public class CompositeDefaultConstructor : IDefaultConstructor
    {
        private readonly IDefaultConstructor[] defaultConstructors;

        public CompositeDefaultConstructor()
            : this(new IDefaultConstructor[]
                {
                    new ConstructorSetByUser(), 
                    new ConstructorWithMinimalDependencies()
                })
        {
        }

        public CompositeDefaultConstructor(IDefaultConstructor[] defaultConstructors)
        {
            this.defaultConstructors = defaultConstructors;
        }

        public void Set(ConstructorInfo[] constructorInfoList, TypeHandle configuration)
        {
            foreach (var defaultConstructor in defaultConstructors)
            {
                defaultConstructor.Set(constructorInfoList,configuration);
                if (configuration.Default != null)
                    return;
            }
        }
    }

    public class ConstructorSetByUser : IDefaultConstructor
    {
        public void Set(ConstructorInfo[] constructorInfoList, TypeHandle configuration)
        {
            for (var i = 0; i < constructorInfoList.Length;i++ )
            {
                if (constructorInfoList[i].GetCustomAttribute(typeof (DefaultConstructorAttribute)) == null) 
                    continue;
                configuration.Default = configuration.Constructors[i];
                return;
            }
        }
    }

    public class ConstructorWithMinimalDependencies : IDefaultConstructor
    {
        public void Set(ConstructorInfo[] constructorInfoList, TypeHandle configuration)
        {
            var countParamters = int.MaxValue;
            for (var i = 0; i < constructorInfoList.Length; i++)
            {
                var parameters = constructorInfoList[i].GetParameters();
                if (parameters.Length >= countParamters) 
                    continue;
                countParamters = parameters.Length;
                configuration.Default = configuration.Constructors[i];
            }
        }
    }

    [AttributeUsage(AttributeTargets.Constructor, Inherited = false, AllowMultiple = false)]
    public sealed class DefaultConstructorAttribute : Attribute
    {
    }
}